namespace ResetConstruct {
	// 原来的类型满足不了，重新做一下类型来满足新的需求
	//

	// 比如有个无组类型已经固定，我想新加一个元素类型
	type tuple = [1, 2, 3];

	type AddTuple<Arr extends unknown[], T extends number> = [...Arr, T];

	type nTuple = AddTuple<[1, 2, 3], 4>;

	// 实现unshif 向原有元组中头添加一个元素

	type UnshiftResult<Arr extends unknown[], Ele> = [Ele, ...Arr];

	// test
	type unshiftArr = UnshiftResult<[1, 2, 3], 9>;

	// 希望把两个元组合并起来，组成一个相互映射的元组类型

	type Zip<
		OneArr extends unknown[],
		TowArr extends unknown[],
	> = OneArr extends [infer One, infer Two]
		? TowArr extends [infer A, infer B]
			? [[One, A], [Two, B]]
			: []
		: [];

	type newZip = Zip<[1, 2], ["zhangsan", "lisi"]>;

	// 希望有多个数组元素都能被支持

	type Zip1<
		OneArr extends unknown[],
		TowArr extends unknown[],
	> = OneArr extends [infer A, ...arest: infer ARest]
		? TowArr extends [infer B, ...brest: infer BRest]
			? [[A, B], ...Zip1<ARest, BRest>]
			: []
		: [];

	type newZip2 = Zip1<
		[1, 2, 3, 4, 5],
		["zhangsan", "lisi", "zhao666", "wangerma", "chengsan"]
	>;

	// 处理一个把字符串首字母大写，其它不变

	type MyCapStr<T extends string> = T extends `${infer A}${infer Str}`
		? `${Uppercase<A>}${Str}`
		: T;

	type CapStr = MyCapStr<"hello">;

	// 实现 zhang_yuan_yuan 转成 zhangYuanYuan

	type CamelCaes<T extends string> =
		T extends `${infer First}_${infer FirstChar}${infer Rest}`
			? `${First}${Uppercase<FirstChar>}${CamelCaes<Rest>}`
			: T;

	type TestCameCase = CamelCaes<"zhang_yuan_yuan">;

	// 指定删除字符串的某个特定字符
	// 比如把 zhang_yuan_yuan 中的 _ 删除，变成 zhangyuanyuan

	type DropChar<
		T extends string,
		Flag extends string,
	> = T extends `${infer First}${Flag}${infer Rest}`
		? `${First}${DropChar<Rest, Flag>}`
		: T;

	type TestDropChar = DropChar<"zhang_yuan_yuan", "_">;
	type TestDropChar2 = DropChar<"zhang~~~~yuan~~yuan~~~", "~">;

	// 做一个函数类型重新构造
	// 这种只能放前面
	type FuncRest<F extends Function, B extends number> = F extends (
		...arg: infer Arg
	) => infer ReturnType
		? (arg0: B, ...arg: Arg) => ReturnType
		: F;

	// 能不把参数放在后面呢, 这种方法值得学习
	type FuncRest2<F extends Function, B extends number> = F extends (
		...arg: infer Arg
	) => infer ReturnType
		? (...arg: [...Arg, B]) => ReturnType
		: F;

	type TestFuncReset = FuncRest<(a: string, name: string) => string, number>;
	type TestFuncReset2 = FuncRest2<(a: string, b: boolean) => string, number>;

	// 对象类型的重新构造
	//

	type MappingObj<T extends Record<string, unknown>> = {
		[Key in keyof T]: [T[Key], T[Key], T[Key], T[Key]];
	};

	type TestMappingObj = MappingObj<{ a: 1; b: "study" }>;

	// 把Object 类型的对象 key 转成大写
	type UpperKey<Obj extends Record<string, any>> = {
		[key in keyof Obj as Uppercase<key & string>]: Obj[key]; // key & string 这个一定要加，确保这个转的为 string 类型
	};

	type TestUpperKey = UpperKey<{ name: "zhangsan"; age: 19 }>;

	// 给类型都加上readonly

	type ToReadonly<T extends Record<string, unknown>> = {
		readonly [K in keyof T]: T[K];
	};

	type TestToReadonly = ToReadonly<{ name: "zhangsan"; age: 19 }>;

	// 给类型都加上 ？ 设置为可选参数

	type ToPartial<T extends Record<string, unknown>> = {
		[K in keyof T]?: T[K];
	};

	type TestToPartial = ToPartial<{ name: "zhangsan"; age: 19 }>;

	// 去掉对象中所有 readonly

	type RemoveAllReadonly<T extends Record<string, unknown>> = {
		-readonly [K in keyof T]: T[K];
	};

	type TestRemoveAllReadonly = RemoveAllReadonly<{
		readonly name: "zhangsan";
		age: 19;
	}>;

	// 去掉对象中所有 ?

	type RemoveAllChecked<T extends Record<string, unknown>> = {
		-readonly [K in keyof T]-?: T[K];
	};

	type TestRemoveAllChecked = RemoveAllChecked<{
		readonly name?: "zhangsan";
		age?: 19;
	}>;

	// 按传的key 类型， 过滤掉不需要的Key值；
	export interface Person {
		name: string;
		age: number;
		hibbit: string[];
	}

	type FilterByValueType<T extends Record<string, any>, F> = {
		[K in keyof T as T[K] extends F ? K : never]: T[K];
	};

	type TestFilterByValueType = FilterByValueType<Person, string | number>;
}
